﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using NetTopologySuite.Geometries;
using NetTopologySuite.IO;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.Runtime;

namespace ConsoleApp
{
    public class Geojson2CADHelper
    {
        // 转换GeoJSON文件为CAD文件
        public void Convert(string geoJsonPath, string cadPath)
        {
            try
            {
                // 读取GeoJSON文件
                string jsonContent = File.ReadAllText(geoJsonPath);

                // 解析GeoJSON
                JObject geoJson = JObject.Parse(jsonContent);
                string type = geoJson["type"].ToString();

                // 创建新的CAD文档
                Document doc = Application.DocumentManager.MdiActiveDocument;
                Database db = doc.Database;
                Editor ed = doc.Editor;

                // 开始事务处理
                using (Transaction tr = db.TransactionManager.StartTransaction())
                {
                    // 获取块表
                    BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead);

                    // 获取模型空间
                    BlockTableRecord btr = (BlockTableRecord)tr.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite);

                    // 根据GeoJSON类型处理
                    if (type == "FeatureCollection")
                    {
                        ProcessFeatureCollection(geoJson, btr, tr);
                    }
                    else if (type == "Feature")
                    {
                        ProcessFeature(geoJson, btr, tr);
                    }
                    else if (type == "GeometryCollection")
                    {
                        ProcessGeometryCollection(geoJson, btr, tr);
                    }
                    else
                    {
                        // 处理单个几何类型
                        ProcessGeometry(geoJson, btr, tr);
                    }

                    // 提交事务
                    tr.Commit();
                }

                // 保存CAD文件
                db.SaveAs(cadPath, DwgVersion.Current);

                Console.WriteLine($"成功将GeoJSON转换为CAD并保存到: {cadPath}");
            }
            catch (System.Exception ex)
            {
                Console.WriteLine($"转换过程中发生错误: {ex.Message}");
                Console.WriteLine($"堆栈跟踪: {ex.StackTrace}");
            }
        }

        // 处理FeatureCollection
        private void ProcessFeatureCollection(JObject featureCollection, BlockTableRecord btr, Transaction tr)
        {
            var features = featureCollection["features"].Children<JObject>();
            foreach (var feature in features)
            {
                ProcessFeature(feature, btr, tr);
            }
        }

        // 处理Feature
        private void ProcessFeature(JObject feature, BlockTableRecord btr, Transaction tr)
        {
            JObject geometry = (JObject)feature["geometry"];
            JObject properties = (JObject)feature["properties"];

            // 处理几何
            ProcessGeometry(geometry, btr, tr, properties);
        }

        // 处理GeometryCollection
        private void ProcessGeometryCollection(JObject geometryCollection, BlockTableRecord btr, Transaction tr, JObject properties = null)
        {
            var geometries = geometryCollection["geometries"].Children<JObject>();
            foreach (var geometry in geometries)
            {
                ProcessGeometry(geometry, btr, tr, properties);
            }
        }

        // 处理几何对象
        private void ProcessGeometry(JObject geometry, BlockTableRecord btr, Transaction tr, JObject properties = null)
        {
            if (geometry == null || geometry["type"] == null)
                return;

            string geometryType = geometry["type"].ToString();

            switch (geometryType)
            {
                case "Point":
                    CreatePoint(geometry, btr, tr, properties);
                    break;
                case "MultiPoint":
                    CreateMultiPoint(geometry, btr, tr, properties);
                    break;
                case "LineString":
                    CreateLineString(geometry, btr, tr, properties);
                    break;
                case "MultiLineString":
                    CreateMultiLineString(geometry, btr, tr, properties);
                    break;
                case "Polygon":
                    CreatePolygon(geometry, btr, tr, properties);
                    break;
                case "MultiPolygon":
                    CreateMultiPolygon(geometry, btr, tr, properties);
                    break;
                default:
                    Console.WriteLine($"不支持的几何类型: {geometryType}");
                    break;
            }
        }

        // 创建点
        // 创建点
        private void CreatePoint(JObject pointGeometry, BlockTableRecord btr, Transaction tr, JObject properties = null)
        {
            var coordinates = pointGeometry["coordinates"].ToObject<List<double>>();
            double x = coordinates[0];
            double y = coordinates[1];
            double z = coordinates.Count > 2 ? coordinates[2] : 0;

            // 移除using语句
            Point3d point = new Point3d(x, y, z);

            using (DBPoint dbPoint = new DBPoint(point))
            {
                // 设置点的属性
                SetEntityProperties(dbPoint, properties);

                // 添加到模型空间
                btr.AppendEntity(dbPoint);
                tr.AddNewlyCreatedDBObject(dbPoint, true);
            }
        }
        // 创建多点
        private void CreateMultiPoint(JObject multiPointGeometry, BlockTableRecord btr, Transaction tr, JObject properties = null)
        {
            var points = multiPointGeometry["coordinates"].ToObject<List<List<double>>>();

            foreach (var pointCoords in points)
            {
                double x = pointCoords[0];
                double y = pointCoords[1];
                double z = pointCoords.Count > 2 ? pointCoords[2] : 0;

                Point3d point = new Point3d(x, y, z);
                
                using (DBPoint dbPoint = new DBPoint(point))
                {
                    // 设置点的属性
                    SetEntityProperties(dbPoint, properties);

                    // 添加到模型空间
                    btr.AppendEntity(dbPoint);
                    tr.AddNewlyCreatedDBObject(dbPoint, true);
                }
                
            }
        }

        // 创建线
        private void CreateLineString(JObject lineStringGeometry, BlockTableRecord btr, Transaction tr, JObject properties = null)
        {
            var coordinates = lineStringGeometry["coordinates"].ToObject<List<List<double>>>();

            if (coordinates.Count < 2)
                return;

            using (Polyline polyline = new Polyline())
            {
                for (int i = 0; i < coordinates.Count; i++)
                {
                    var coord = coordinates[i];
                    double x = coord[0];
                    double y = coord[1];
                    double z = coord.Count > 2 ? coord[2] : 0;

                    polyline.AddVertexAt(i, new Point2d(x, y), 0, 0, 0);
                }

                // 设置线的属性
                SetEntityProperties(polyline, properties);

                // 添加到模型空间
                btr.AppendEntity(polyline);
                tr.AddNewlyCreatedDBObject(polyline, true);
            }
        }

        // 创建多线
        private void CreateMultiLineString(JObject multiLineStringGeometry, BlockTableRecord btr, Transaction tr, JObject properties = null)
        {
            var lineStrings = multiLineStringGeometry["coordinates"].ToObject<List<List<List<double>>>>();

            foreach (var lineStringCoords in lineStrings)
            {
                if (lineStringCoords.Count < 2)
                    continue;

                using (Polyline polyline = new Polyline())
                {
                    for (int i = 0; i < lineStringCoords.Count; i++)
                    {
                        var coord = lineStringCoords[i];
                        double x = coord[0];
                        double y = coord[1];
                        double z = coord.Count > 2 ? coord[2] : 0;

                        polyline.AddVertexAt(i, new Point2d(x, y), 0, 0, 0);
                    }

                    // 设置线的属性
                    SetEntityProperties(polyline, properties);

                    // 添加到模型空间
                    btr.AppendEntity(polyline);
                    tr.AddNewlyCreatedDBObject(polyline, true);
                }
            }
        }

        // 创建多边形
        private void CreatePolygon(JObject polygonGeometry, BlockTableRecord btr, Transaction tr, JObject properties = null)
        {
            var coordinates = polygonGeometry["coordinates"].ToObject<List<List<List<double>>>>();

            // 处理外部环
            var exteriorRing = coordinates[0];

            using (Polyline exteriorPolyline = new Polyline())
            {
                for (int i = 0; i < exteriorRing.Count; i++)
                {
                    var coord = exteriorRing[i];
                    double x = coord[0];
                    double y = coord[1];
                    double z = coord.Count > 2 ? coord[2] : 0;

                    exteriorPolyline.AddVertexAt(i, new Point2d(x, y), 0, 0, 0);
                }

                // 闭合多边形
                exteriorPolyline.Closed = true;

                // 设置多边形属性
                SetEntityProperties(exteriorPolyline, properties);

                // 添加到模型空间
                btr.AppendEntity(exteriorPolyline);
                tr.AddNewlyCreatedDBObject(exteriorPolyline, true);

                // 处理内部环（孔洞）
                for (int i = 1; i < coordinates.Count; i++)
                {
                    var interiorRing = coordinates[i];

                    using (Polyline interiorPolyline = new Polyline())
                    {
                        for (int j = 0; j < interiorRing.Count; j++)
                        {
                            var coord = interiorRing[j];
                            double x = coord[0];
                            double y = coord[1];
                            double z = coord.Count > 2 ? coord[2] : 0;

                            interiorPolyline.AddVertexAt(j, new Point2d(x, y), 0, 0, 0);
                        }

                        // 闭合孔洞
                        interiorPolyline.Closed = true;

                        // 设置孔洞属性
                        SetEntityProperties(interiorPolyline, properties);

                        // 添加到模型空间
                        btr.AppendEntity(interiorPolyline);
                        tr.AddNewlyCreatedDBObject(interiorPolyline, true);
                    }
                }
            }
        }

        // 创建多多边形
        private void CreateMultiPolygon(JObject multiPolygonGeometry, BlockTableRecord btr, Transaction tr, JObject properties = null)
        {
            var polygons = multiPolygonGeometry["coordinates"].ToObject<List<List<List<List<double>>>>>();

            foreach (var polygonCoords in polygons)
            {
                JObject polygonJson = new JObject
                {
                    ["type"] = "Polygon",
                    ["coordinates"] = JToken.FromObject(polygonCoords)
                };

                CreatePolygon(polygonJson, btr, tr, properties);
            }
        }

        // 设置实体属性
        private void SetEntityProperties(Entity entity, JObject properties)
        {
            if (properties == null)
                return;

            // 尝试设置颜色
            if (properties.ContainsKey("color"))
            {
                string colorStr = properties["color"].ToString();
                try
                {
                    // 尝试解析颜色
                    System.Drawing.Color color = System.Drawing.ColorTranslator.FromHtml(colorStr);
                    entity.ColorIndex = (short)ColorToColorIndex(color);
                }
                catch
                {
                    // 如果颜色解析失败，使用默认颜色
                }
            }

            // 尝试设置图层
            if (properties.ContainsKey("layer") && !string.IsNullOrEmpty(properties["layer"].ToString()))
            {
                string layerName = properties["layer"].ToString();
                entity.Layer = layerName;
            }

            // 可以添加更多属性设置...
        }

        // 将系统颜色转换为AutoCAD颜色索引
        private int ColorToColorIndex(System.Drawing.Color color)
        {
            // 这里使用简单的RGB到ACI映射，实际应用中可能需要更复杂的算法
            int r = color.R;
            int g = color.G;
            int b = color.B;

            // 计算亮度
            double luminance = 0.299 * r + 0.587 * g + 0.114 * b;

            // 根据亮度分配颜色索引
            if (luminance > 200)
                return 254; // 白色
            else if (luminance < 50)
                return 1;   // 黑色
            else
                return (r > g && r > b) ? 1   // 红色
                     : (g > b) ? 3           // 绿色
                     : 5;                   // 蓝色
        }
    }
}
